package com.fjnu.dao.impl;

import com.fjnu.dao.UserDao;
import com.fjnu.dto.UserConditionDto;
import com.fjnu.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 用户模块DAO层实现类，基于Spring JDBC Template实现用户相关数据库操作
 * 对应实验任务中UserDao模块的8个业务方法
 */
@Repository
public class UserDaoImpl implements UserDao {

    // 注入Spring JDBC核心模板对象，用于执行数据库操作
    @Autowired
    private JdbcTemplate jdbcTemplate;

    // 内部RowMapper实现类，用于将SQL查询结果集映射为User实体对象
    private final UserRowMapper userRowMapper = new UserRowMapper();

    /**
     * 新增用户
     * @param newUser 待新增的用户实体
     * @return 新增成功返回1，失败返回0
     */
    @Override
    public int insert(User newUser) {
        if(newUser == null || newUser.getName() == null)
            return 0;
        // 构建新增用户的SQL语句，对应tb_user表字段
        String sql = "INSERT INTO tb_user (name, password, salt, create_time, gender, score, status, email) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
        // 执行更新操作，返回影响行数（1表示成功，0表示失败）
        int affectedRows = jdbcTemplate.update(sql,
                newUser.getName(),
                newUser.getPassword(),
                newUser.getSalt(),
                newUser.getCreateTime(),
                newUser.getGender(),
                newUser.getScore(),
                newUser.getStatus(),
                newUser.getEmail());
        // 按照实验要求，返回1或0表示操作结果
        return affectedRows > 0 ? 1 : 0;
    }

    /**
     * 为用户分配单个角色
     * @param userId 用户ID
     * @param roleId 角色ID
     * @return 分配成功返回1，失败返回0
     */
    @Override
    public int insertUserRole(Integer userId, Integer roleId) {
        if (userId == null || roleId == null) {
            return 0;
        }
        // 构建用户-角色关联表（tb_user_role）的新增SQL
        String sql = "INSERT INTO tb_user_role (user_id, role_id) VALUES (?, ?)";
        // 执行更新操作，返回影响行数
        int affectedRows = jdbcTemplate.update(sql, userId, roleId);
        return affectedRows > 0 ? 1 : 0;
    }

    /**
     * 为用户批量分配多个角色
     * @param userId 用户ID
     * @param roleIds 角色ID列表
     * @return 批量插入成功的记录数
     */
    @Override
    public int batchInsertUserRoles(Integer userId, List<Integer> roleIds) {
        if (roleIds == null || roleIds.isEmpty() || userId == null) {
            return 0;
        }
        // 构建批量新增用户-角色关联的SQL
        String sql = "INSERT INTO tb_user_role (user_id, role_id) VALUES (?, ?)";
        // 准备批量参数：每个参数组包含userId和单个roleId
        List<Object[]> batchParams = new ArrayList<>();
        for (Integer roleId : roleIds) {
            batchParams.add(new Object[]{userId, roleId});
        }
        // 执行批量更新，返回每个操作的影响行数数组
        int[] affectedRowsArray = jdbcTemplate.batchUpdate(sql, batchParams);
        // 统计成功插入的记录数（影响行数>0视为成功）
        int successCount = 0;
        for (int affectedRows : affectedRowsArray) {
            if (affectedRows > 0) {
                successCount++;
            }
        }
        // 按照实验要求返回成功的记录数
        return successCount;
    }

    /**
     * 修改用户密码
     * @param userId 用户ID
     * @param newPassword 新密码
     * @return 修改成功返回1，失败返回0
     */
    @Override
    public int updatePassword(Integer userId, String newPassword) {
        // 构建更新用户密码的SQL，仅更新password字段
        String sql = "UPDATE tb_user SET password = ? WHERE user_id = ?";
        int affectedRows = jdbcTemplate.update(sql, newPassword, userId);
        return affectedRows > 0 ? 1 : 0;
    }

    /**
     * 按增量修改用户分数
     * @param userId 用户ID
     * @param incrementedScore 分数增量（可正可负）
     * @return 修改成功返回1，失败返回0
     */
    @Override
    public int updateScore(Integer userId, Long incrementedScore) {
        // 构建增量更新分数的SQL，使用"score + ?"实现增量逻辑
        String sql = "UPDATE tb_user SET score = score + ? WHERE user_id = ?";
        int affectedRows = jdbcTemplate.update(sql, incrementedScore, userId);
        // 按照实验要求，返回1或0表示操作结果
        return affectedRows > 0 ? 1 : 0;
    }

    /**
     * 通过用户名和密码查询用户
     * @param username 用户名
     * @param password 密码
     * @return 匹配的User实体，无匹配结果返回Null
     */
    @Override
    public User selectByNameAndPwd(String username, String password) {
        // 构建按用户名和密码查询的SQL，精确匹配
        String sql = "SELECT * FROM tb_user WHERE name = ? AND password = ?";
        // 执行查询，获取用户列表（理论上仅0或1条数据）
        List<User> userList = jdbcTemplate.query(sql, userRowMapper, username, password);
        // 无匹配结果返回Null，有匹配结果返回第一个用户
        return userList.isEmpty() ? null : userList.get(0);
    }

    /**
     * 根据筛选条件查询用户
     * @param userConditionDto 用户查询条件DTO
     * @return 匹配条件的用户列表，无结果返回空列表（而非Null）
     */
    @Override
    public List<User> selectByCondition(UserConditionDto userConditionDto) {
        // 构建动态SQL：基础查询语句
        StringBuilder sqlBuilder = new StringBuilder("SELECT * FROM tb_user WHERE 1=1");
        // 存储动态条件的参数列表
        List<Object> params = new ArrayList<>();

        // 1. 用户名模糊查询（若条件不为空）
        if (userConditionDto.getUsername() != null && !userConditionDto.getUsername().trim().isEmpty()) {
            sqlBuilder.append(" AND name LIKE ?");
            params.add("%" + userConditionDto.getUsername().trim() + "%");
        }

        // 2. 邮箱精确查询（若条件不为空）
        if (userConditionDto.getEmail() != null && !userConditionDto.getEmail().trim().isEmpty()) {
            sqlBuilder.append(" AND email = ?");
            params.add(userConditionDto.getEmail().trim());
        }

        // 3. 状态精确查询（若条件不为空）
        if (userConditionDto.getStatus() != null) {
            sqlBuilder.append(" AND status = ?");
            params.add(userConditionDto.getStatus());
        }

        // 4. 最低分数查询（若条件不为空）
        if (userConditionDto.getMinScore() != null) {
            sqlBuilder.append(" AND score >= ?");
            params.add(userConditionDto.getMinScore());
        }

        // 5. 最高分数查询（若条件不为空）
        if (userConditionDto.getMaxScore() != null) {
            sqlBuilder.append(" AND score <= ?");
            params.add(userConditionDto.getMaxScore());
        }

        // 执行动态SQL查询，返回匹配的用户列表
        return jdbcTemplate.query(sqlBuilder.toString(), userRowMapper, params.toArray());
    }

    /**
     * 根据筛选条件查询指定范围的用户（分页查询）
     * @param userConditionDto 用户查询条件DTO
     * @param startIndex 起始索引（包含）
     * @param endIndex 结束索引（包含）
     * @return 指定范围且匹配条件的用户列表，无结果返回空列表（而非Null）
     */
    @Override
    public List<User> selectByConditionWithLimit(UserConditionDto userConditionDto, Integer startIndex, Integer endIndex) {
        // 1. 复用条件查询的动态SQL逻辑
        StringBuilder sqlBuilder = new StringBuilder("SELECT * FROM tb_user WHERE 1=1");
        List<Object> params = new ArrayList<>();

        if (userConditionDto.getUsername() != null && !userConditionDto.getUsername().trim().isEmpty()) {
            sqlBuilder.append(" AND name LIKE ?");
            params.add("%" + userConditionDto.getUsername().trim() + "%");
        }
        if (userConditionDto.getEmail() != null && !userConditionDto.getEmail().trim().isEmpty()) {
            sqlBuilder.append(" AND email = ?");
            params.add(userConditionDto.getEmail().trim());
        }
        if (userConditionDto.getStatus() != null) {
            sqlBuilder.append(" AND status = ?");
            params.add(userConditionDto.getStatus());
        }
        if (userConditionDto.getMinScore() != null) {
            sqlBuilder.append(" AND score >= ?");
            params.add(userConditionDto.getMinScore());
        }
        if (userConditionDto.getMaxScore() != null) {
            sqlBuilder.append(" AND score <= ?");
            params.add(userConditionDto.getMaxScore());
        }

        // 2. 添加分页逻辑：LIMIT 起始索引, 查询条数（结束索引-起始索引+1）
        sqlBuilder.append(" LIMIT ?, ?");
        params.add(startIndex);
        params.add(endIndex - startIndex + 1);

        // 执行分页查询，返回指定范围的用户列表
        return jdbcTemplate.query(sqlBuilder.toString(), userRowMapper, params.toArray());
    }

    /**
     * 内部静态类：实现RowMapper接口，将ResultSet映射为User实体
     */
    private static class UserRowMapper implements RowMapper<User> {
        @Override
        public User mapRow(ResultSet rs, int rowNum) throws SQLException {
            User user = new User();
            // 映射tb_user表字段到User实体属性，严格匹配实验相关数据结构
            user.setUserId(rs.getInt("user_id"));
            user.setName(rs.getString("name"));
            user.setPassword(rs.getString("password"));
            user.setSalt(rs.getString("salt"));
            // 将SQL的datetime类型转换为LocalDateTime，确保时间字段映射准确性
            user.setCreateTime(rs.getTimestamp("create_time").toLocalDateTime());
            // 按要求将gender字段从Byte类型调整为int类型映射
            user.setGender(rs.getInt("gender"));
            user.setScore(rs.getLong("score"));
            user.setStatus(rs.getInt("status"));
            user.setEmail(rs.getString("email"));
            return user;
        }
    }
}